<template>
  <div class="conversion-history">
    <div class="header">
      <div class="header-text">
        <h2>转换历史</h2>
        <h3>只保留最近的 7 条记录</h3>
      </div>
      <button v-if="!loading && history.length > 0" @click="refresh" class="refresh-btn">
        <span class="icon">🔄</span> 刷新
      </button>
    </div>
    
    <div v-if="loading" class="loading">
      <div class="spinner"></div>
      <p>加载中...</p>
    </div>
    
    <div v-else-if="history.length === 0" class="empty">
      <div class="empty-icon">📂</div>
      <p>暂无转换记录</p>
    </div>
    
    <div v-else class="history-list">
      <div 
        v-for="item in history" 
        :key="item.id" 
        class="history-item"
        :class="{ 'status-failed': item.conversionStatus === 3 }"
      >
        <!-- 预览图 -->
        <div class="preview-section">
          <!-- DOCX -> PDF 专用封面 -->
          <div 
            v-if="item.conversionStatus === 2 && isDocxToPdf(item)" 
            class="docx-preview-card"
          >
            <img :src="pdfPlaceholder" alt="PDF" class="docx-preview-image" />
            <div class="docx-preview-filename">{{ item.originalFilename }}</div>
          </div>
          <!-- 成功状态 - 优先使用缩略图（视频转GIF的首帧预览），否则使用输出文件 -->
          <!-- 🔑 优化：添加占位符和加载状态 -->
          <div v-else-if="item.conversionStatus === 2 && (!imageLoaded[item.id] || imageLoading[item.id])" class="image-placeholder">
            <div class="image-skeleton"></div>
          </div>
          <img 
            v-if="item.conversionStatus === 2 && item.thumbnailUrl" 
            :src="item.thumbnailUrl" 
            :alt="item.originalFilename"
            :data-item-id="item.id"
            class="thumbnail-preview"
            :class="{ 
              'thumbnail-gif': item.conversionType === 'VIDEO_TO_GIF',
              'image-loaded': imageLoaded[item.id],
              'image-loading': imageLoading[item.id]
            }"
            :loading="getImageLoadingPriority(item)"
            decoding="async"
            @load="handleImageLoad(item.id)"
            @error="handleImageError"
            @loadstart="handleImageLoadStart(item.id)"
          />
          <img 
            v-else-if="item.conversionStatus === 2 && item.outputUrl" 
            :src="getOptimizedImageUrl(item)" 
            :alt="item.originalFilename"
            :data-item-id="item.id"
            class="output-preview"
            :class="{ 
              'output-preview-gif': item.conversionType === 'VIDEO_TO_GIF',
              'image-loaded': imageLoaded[item.id],
              'image-loading': imageLoading[item.id]
            }"
            :loading="getImageLoadingPriority(item)"
            decoding="async"
            @load="handleImageLoad(item.id)"
            @error="handleImageError"
            @loadstart="handleImageLoadStart(item.id)"
          />
          <!-- 转换中 -->
          <div v-else-if="item.conversionStatus === 1" class="status-badge converting">
            转换中...
          </div>
          <!-- 转换失败 -->
          <div v-else-if="item.conversionStatus === 3" class="status-badge failed">
            转换失败
          </div>
          <!-- 等待中 -->
          <div v-else class="status-badge pending">
            等待中...
          </div>
          
          <!-- 转换类型标签 -->
          <div v-if="item.conversionType" class="type-badge">
            {{ item.conversionTypeDescription || item.conversionType }}
          </div>
        </div>
        
        <!-- 记录信息 -->
        <div class="info-section">
          <div class="filename">{{ item.originalFilename }}</div>
          <div class="meta-info">
            <span
              class="meta-item"
              v-if="!isPdfType(item)"
            >
              <span class="label">尺寸:</span>
              <span v-if="item.outputWidth && item.outputHeight">{{ item.outputWidth }}×{{ item.outputHeight }}</span>
              <span v-else>-</span>
            </span>
            <span class="meta-item">
              <span class="label">大小:</span>
              <span v-if="item.outputFileSizeFormatted">{{ item.outputFileSizeFormatted }}</span>
              <span v-else-if="item.outputFileSize">{{ formatFileSize(item.outputFileSize) }}</span>
              <span v-else>-</span>
            </span>
            <span class="meta-item">
              <span class="label">时间:</span>
              <span>{{ formatTime(item.createTime) }}</span>
            </span>
          </div>
          <div v-if="item.errorMessage" class="error-message">
            {{ item.errorMessage }}
          </div>
        </div>
        
        <!-- 操作按钮 -->
        <div class="actions">
          <button 
            v-if="item.conversionStatus === 2 && item.outputUrl && canPreview(item)" 
            @click="handlePreview(item)"
            class="action-btn preview"
            :title="'预览' + getFileTypeName(item)"
          >
          预览
          </button>
          <button 
            v-if="item.conversionStatus === 2 && item.outputUrl" 
            @click="handleDownload(item)"
            class="action-btn download"
            title="下载"
            :disabled="downloading === item.id"
          >
            <span v-if="downloading === item.id">⏳</span>
            <span v-else>下载</span>
          </button>
          <button 
            @click="handleDelete(item.id)" 
            class="action-btn delete"
            title="删除"
            :disabled="deleting === item.id"
          >
            <span v-if="deleting === item.id">⏳</span>
            <span v-else>删除</span>
          </button>
        </div>
      </div>
    </div>
    
    <!-- 文件预览模态框 -->
    <div v-if="previewItem" class="preview-modal" @click="closePreview">
      <div class="preview-modal-content" @click.stop>
        <div class="preview-modal-header">
          <img
            v-if="isPdfType(previewItem)"
            :src="pdfPlaceholder"
            alt="PDF"
            class="preview-modal-icon"
          />
          <div class="preview-modal-title">{{ previewItem.originalFilename }}</div>
          <button class="preview-close-btn" @click="closePreview" title="关闭">
            ✕
          </button>
        </div>

        <div class="preview-modal-meta">
          <span>类型: {{ previewItem.conversionTypeDescription }}</span>
          <span v-if="!isPdfType(previewItem) && previewItem.outputWidth && previewItem.outputHeight">
            尺寸: {{ previewItem.outputWidth }}×{{ previewItem.outputHeight }}
          </span>
          <span v-if="previewItem.outputFileSizeFormatted">
            大小: {{ previewItem.outputFileSizeFormatted }}
          </span>
          <span>{{ formatTime(previewItem.createTime) }}</span>
        </div>
        
        <!-- 文件预览容器 -->
        <div class="preview-file-container">
          <!-- 加载等待页面 -->
          <div v-if="previewLoading" class="preview-loading">
            <div class="preview-loading-spinner"></div>
            <p class="preview-loading-text">正在加载预览...</p>
            <p class="preview-loading-hint" v-if="previewItem.conversionType === 'VIDEO_TO_GIF'">GIF文件较大，请稍候</p>
          </div>
          
          <!-- GIF/图片预览 - 优化性能 -->
          <img 
            v-if="isImageType(previewItem) && previewImageReady"
            :src="previewUrl" 
            :alt="previewItem.originalFilename"
            class="preview-file"
            :class="{ 'preview-gif': previewItem.conversionType === 'VIDEO_TO_GIF' }"
            loading="eager"
            decoding="async"
            @load="handleGifLoad"
            @error="handlePreviewError"
          />
          <!-- SVG预览（改用img，避免部分移动端object空白） -->
          <img
            v-else-if="isSvgType(previewItem) && previewImageReady"
            :src="previewUrl"
            :alt="previewItem.originalFilename"
            class="preview-file preview-svg-img"
            loading="eager"
            decoding="async"
            @error="handlePreviewError"
          />
          <!-- PDF 预览 -->
          <iframe
            v-else-if="isPdfType(previewItem) && !previewLoading"
            :src="previewUrl"
            title="PDF 预览"
            class="preview-pdf-frame"
          ></iframe>
          <!-- 其他类型暂不支持 -->
          <div v-else class="preview-placeholder-text">
            暂不支持此类型的在线预览
          </div>
        </div>
        
        <div class="preview-modal-actions">
          <button 
            class="preview-modal-btn primary" 
            @click="handleDownload(previewItem)"
            :disabled="downloading === previewItem.id"
          >
            <span v-if="downloading === previewItem.id">⏳ 下载中...</span>
            <span v-else>⬇️ 下载{{ getFileTypeName(previewItem) }}</span>
          </button>
          <button class="preview-modal-btn secondary" @click="closePreview">关闭</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { getUserHistory, deleteUserConversion } from '@/api/user'
import { toastError, toastSuccess } from '@/utils/toast'
import pdfPlaceholder from '@/assets/pdf.svg'

// 配置常量
const HISTORY_CONFIG = {
  limit: 7           // 历史记录条数
}

const history = ref([])
const loading = ref(true)
const deleting = ref(null)
const downloading = ref(null)
const previewItem = ref(null) // 当前预览的项目
const imageLoaded = ref({}) // 🔑 图片加载状态
const imageLoading = ref({}) // 🔑 图片加载中状态
const previewLoading = ref(false) // 🔑 GIF预览加载状态
const previewImageReady = ref(false) // 🔑 GIF预览图片是否准备好
const previewObjectUrl = ref(null) // 🔑 预览使用的本地URL（用于加速与释放）
const previewUrl = ref('') // 当前预览展示的URL

// 加载转换历史
const loadHistory = async () => {
  try {
    loading.value = true
    // 使用配置对象，更易扩展
    const response = await getUserHistory(HISTORY_CONFIG)
    history.value = response.data || []
    // 🔑 重置图片加载状态
    imageLoaded.value = {}
    imageLoading.value = {}
    // 🔑 预加载前3张图片
    preloadFirstImages()
  } catch (error) {
    console.error('加载转换历史失败:', error)
    history.value = []
  } finally {
    loading.value = false
  }
}

// 🔑 预加载前3张图片
const preloadFirstImages = () => {
  const firstThree = history.value.slice(0, 3)
  firstThree.forEach(item => {
    if (item.conversionStatus === 2) {
      const imageUrl = item.thumbnailUrl || item.outputUrl
      if (imageUrl) {
        const preloadUrl = sanitizeUrl(wrapWithProxy(imageUrl))
        const link = document.createElement('link')
        link.rel = 'preload'
        link.as = 'image'
        link.href = preloadUrl
        document.head.appendChild(link)
        // 清理预加载链接
        setTimeout(() => link.remove(), 2000)
      }
    }
  })
}

// 刷新历史记录
const refresh = () => {
  loadHistory()
}

// 打开预览
const handlePreview = async (item) => {
  previewItem.value = item
  previewLoading.value = true
  previewImageReady.value = false
  previewUrl.value = ''
  // 禁止body滚动
  document.body.style.overflow = 'hidden'
  
  if (isPdfType(item)) {
    previewUrl.value = getPreviewUrl(item)
    previewLoading.value = false
    previewImageReady.value = true
    return
  }

  // 预加载图片/GIF，等待完全加载后再显示
  if (isImageType(item) || isSvgType(item)) {
    await preloadPreviewImage(item)
  } else {
    // 非图片类型，直接显示
    previewUrl.value = getPreviewUrl(item)
    previewLoading.value = false
    previewImageReady.value = true
  }
}

// 预加载预览图片（等待完全加载）
const normalizeSvgText = (svgText) => {
  try {
    // 解析并补全必要属性，修复部分SVG在移动端不显示的问题
    const parser = new DOMParser()
    const doc = parser.parseFromString(svgText, 'image/svg+xml')
    const svgEl = doc.documentElement
    if (!svgEl || svgEl.nodeName.toLowerCase() !== 'svg') return svgText
    // xmlns
    if (!svgEl.getAttribute('xmlns')) {
      svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
    }
    // 如果缺少viewBox但有宽高，写入viewBox
    const widthAttr = svgEl.getAttribute('width')
    const heightAttr = svgEl.getAttribute('height')
    if (!svgEl.getAttribute('viewBox')) {
      const widthNum = parseFloat(widthAttr || '0')
      const heightNum = parseFloat(heightAttr || '0')
      if (widthNum > 0 && heightNum > 0) {
        svgEl.setAttribute('viewBox', `0 0 ${widthNum} ${heightNum}`)
      }
    }
    // 移动端可见性：确保宽高存在或用100%展示
    if (!widthAttr && !heightAttr) {
      svgEl.setAttribute('width', '100%')
      svgEl.setAttribute('height', '100%')
      // 若无viewBox，给一个兜底，避免0尺寸
      if (!svgEl.getAttribute('viewBox')) {
        svgEl.setAttribute('viewBox', '0 0 1024 1024')
      }
    }
    // 优化渲染
    svgEl.setAttribute('preserveAspectRatio', svgEl.getAttribute('preserveAspectRatio') || 'xMidYMid meet')
    return new XMLSerializer().serializeToString(svgEl)
  } catch {
    return svgText
  }
}

const preloadPreviewImage = async (item) => {
  // 清理上一次的本地URL
  if (previewObjectUrl.value) {
    try { URL.revokeObjectURL(previewObjectUrl.value) } catch {}
    previewObjectUrl.value = null
  }
  const controller = new AbortController()
  const timeoutId = setTimeout(() => controller.abort(), 30000)
  try {
    // 先用 fetch 预取到内存（可复用 HTTP 缓存）
    const response = await fetch(item.outputUrl, { cache: 'force-cache', signal: controller.signal })
    if (!response.ok) throw new Error('网络错误')

    let objectUrl
    // 对SVG特殊处理：以文本读取并规范化，再以 image/svg+xml 生成Blob，避免部分机型空白
    const contentType = response.headers.get('Content-Type') || ''
    if (isSvgType(item) || contentType.includes('image/svg+xml')) {
      const svgText = await response.text()
      const fixedSvg = normalizeSvgText(svgText)
      const svgBlob = new Blob([fixedSvg], { type: 'image/svg+xml;charset=utf-8' })
      objectUrl = URL.createObjectURL(svgBlob)
    } else {
      const blob = await response.blob()
      // 尝试提前解码（若浏览器支持）
      try { await createImageBitmap(blob) } catch {}
      objectUrl = URL.createObjectURL(blob)
    }

    previewObjectUrl.value = objectUrl
    previewUrl.value = objectUrl
    // GIF 仍做极短延时，给渲染线程时间建立帧缓存
    const extraDelay = (() => {
      if (item.conversionType !== 'VIDEO_TO_GIF') return 0
      const sizeMB = item.outputFileSize
        ? item.outputFileSize / (1024 * 1024)
        : (item.outputFileSizeFormatted
            ? parseFloat(item.outputFileSizeFormatted.replace(/[^0-9.]/g, ''))
            : 5)
      if (sizeMB < 5) return 200
      if (sizeMB < 10) return 400
      if (sizeMB < 20) return 700
      return 1000
    })()
    await new Promise(r => setTimeout(r, extraDelay))
    previewLoading.value = false
    previewImageReady.value = true
  } catch (e) {
    console.warn('预览预取失败，退化到直接显示:', e?.message || e)
    // 失败则退化为原逻辑：直接显示远程URL
    previewUrl.value = getPreviewUrl(item)
    previewLoading.value = false
    previewImageReady.value = true
  } finally {
    clearTimeout(timeoutId)
  }
}

// 关闭预览
const closePreview = () => {
  previewItem.value = null
  previewLoading.value = false
  previewImageReady.value = false
  previewUrl.value = ''
  // 恢复body滚动
  document.body.style.overflow = ''
  // 释放本地URL
  if (previewObjectUrl.value) {
    try { URL.revokeObjectURL(previewObjectUrl.value) } catch {}
    previewObjectUrl.value = null
  }
}

// 判断是否可以预览
const canPreview = (item) => {
  if (isPdfType(item)) {
    return false
  }
  return isImageType(item) || isSvgType(item)
}

// 判断是否为图片类型（GIF等）
const isImageType = (item) => {
  return item.conversionType === 'VIDEO_TO_GIF' || 
         item.conversionType === 'IMAGE_MATTING' ||
         (item.outputFilename && item.outputFilename.match(/\.(gif|jpg|jpeg|png|webp)$/i))
}

// 判断是否为SVG类型
const isSvgType = (item) => {
  return item.conversionType === 'FILE_TO_SVG' || 
         (item.outputFilename && item.outputFilename.endsWith('.svg'))
}

const isPdfType = (item) => {
  return item.conversionType === 'DOCX_TO_PDF' ||
         (item.outputFilename && item.outputFilename.toLowerCase().endsWith('.pdf'))
}

const isDocxToPdf = (item) => item.conversionType === 'DOCX_TO_PDF'

const sanitizeUrl = (url = '') => {
  if (!url || typeof url !== 'string') return ''
  const normalized = url.trim()
  if (!normalized) return ''
  return normalized.replace(/([?&])download=true/g, '$1').replace(/[?&]$/, '')
}

const isProxyUrl = (url = '') => {
  if (!url) return false
  if (url.startsWith('/api/files/proxy')) return true
  if (!url.startsWith('http')) return false
  try {
    const parsed = new URL(url)
    return parsed.pathname.startsWith('/api/files/proxy')
  } catch (error) {
    return false
  }
}

const wrapWithProxy = (url = '') => {
  const normalized = sanitizeUrl(url)
  if (!normalized) return ''
  if (isProxyUrl(normalized)) {
    return normalized
  }
  if (normalized.startsWith('http')) {
    return `/api/files/proxy?url=${encodeURIComponent(normalized)}`
  }
  if (normalized.startsWith('temp://')) {
    const localPath = normalized.substring(7)
    return `/api/files/local?path=${encodeURIComponent(localPath)}`
  }
  return normalized
}

const getPreviewUrl = (item) => {
  if (!item) return ''
  const base = sanitizeUrl(item.outputUrl || item.pdfUrl || item.downloadUrl || '')
  if (isPdfType(item)) {
    return wrapWithProxy(base)
  }
  return base
}

// 获取文件类型名称
const getFileTypeName = (item) => {
  if (item.conversionType === 'VIDEO_TO_GIF') return 'GIF'
  if (item.conversionType === 'FILE_TO_SVG') return 'SVG'
  if (item.conversionType === 'IMAGE_MATTING') return 'PNG'
  if (item.conversionType === 'DOCX_TO_PDF') return 'PDF'
  return '文件'
}

// 下载文件
const handleDownload = async (item) => {
  // 优先使用downloadUrl（如果是COS文件，这是原始COS URL，下载更快）
  // 如果没有downloadUrl，使用outputUrl（可能是代理URL或本地URL）
  const downloadUrl = item.downloadUrl || item.outputUrl
  
  if (!downloadUrl) {
    toastError('下载地址不存在')
    return
  }
  
  try {
    downloading.value = item.id
    
    // 确定文件名
    let filename = item.outputFilename || item.originalFilename || 'output'
    
    // 如果outputFilename是完整URL，提取文件名
    if (filename.startsWith('http://') || filename.startsWith('https://')) {
      const urlParts = filename.split('/')
      filename = urlParts[urlParts.length - 1]
      // 移除查询参数
      const queryIndex = filename.indexOf('?')
      if (queryIndex > 0) {
        filename = filename.substring(0, queryIndex)
      }
    }
    
    // 如果没有扩展名，根据类型添加
    if (!filename.includes('.')) {
      if (item.conversionType === 'VIDEO_TO_GIF') {
        filename += '.gif'
      } else if (item.conversionType === 'FILE_TO_SVG') {
        filename += '.svg'
      } else if (item.conversionType === 'IMAGE_MATTING') {
        filename += '.png'
      }
    }
    
    // 判断是否为外部URL（COS URL或代理URL）
    const isExternalUrl = downloadUrl.startsWith('http://') || downloadUrl.startsWith('https://')
    
    if (isExternalUrl) {
      // 对于外部URL，直接创建下载链接（避免CORS问题）
      const a = document.createElement('a')
      a.href = downloadUrl
      a.download = filename
      a.target = '_blank'  // 在新标签页打开，如果浏览器阻止下载会显示文件
      document.body.appendChild(a)
      a.click()
      a.remove()
      toastSuccess('开始下载')
    } else {
      // 对于本地文件，使用fetch下载
      const response = await fetch(downloadUrl)
      if (!response.ok) {
        throw new Error('下载失败：' + response.statusText)
      }
      
      // 获取Blob
      const blob = await response.blob()
      
      // 创建下载链接
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = filename
      
      document.body.appendChild(a)
      a.click()
      
      // 清理
      URL.revokeObjectURL(url)
      a.remove()
      
      toastSuccess('下载成功')
    }
  } catch (error) {
    console.error('下载失败:', error)
    toastError('下载失败: ' + error.message)
  } finally {
    downloading.value = null
  }
}

// 删除记录
const handleDelete = async (recordId) => {
  try {
    deleting.value = recordId
    await deleteUserConversion(recordId)
    // 从列表中移除
    history.value = history.value.filter(item => item.id !== recordId)
    toastSuccess('删除成功')
  } catch (error) {
    console.error('删除记录失败:', error)
    toastError('删除失败: ' + error.message)
  } finally {
    deleting.value = null
  }
}

// 格式化文件大小
const formatFileSize = (bytes) => {
  if (!bytes) return '-'
  if (bytes < 1024) return bytes + ' B'
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB'
  return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
}

// 格式化时间
const formatTime = (timeStr) => {
  if (!timeStr) return '-'
  const date = new Date(timeStr)
  const now = new Date()
  const diff = now - date
  
  // 小于1分钟
  if (diff < 60000) {
    return '刚刚'
  }
  // 小于1小时
  if (diff < 3600000) {
    return `${Math.floor(diff / 60000)}分钟前`
  }
  // 小于1天
  if (diff < 86400000) {
    return `${Math.floor(diff / 3600000)}小时前`
  }
  // 小于7天
  if (diff < 604800000) {
    return `${Math.floor(diff / 86400000)}天前`
  }
  
  // 超过7天显示具体日期
  return date.toLocaleDateString('zh-CN', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit'
  })
}

// 🔑 获取优化的图片URL（移除时间戳，使用缓存）
const getOptimizedImageUrl = (item) => {
  const url = item?.outputUrl
  if (!url) return ''
  // 代理URL需要保留查询参数才能访问
  if (isProxyUrl(url)) {
    return sanitizeUrl(url)
  }
  // 直接URL则移除时间戳参数，提升缓存命中
  return url.split('?')[0]
}

// 🔑 获取图片加载优先级（前3个立即加载，其他懒加载）
const getImageLoadingPriority = (item) => {
  // 前3个图片立即加载，其他懒加载
  const index = history.value.findIndex(h => h.id === item.id)
  return index < 3 ? 'eager' : 'lazy'
}

// 🔑 图片开始加载
const handleImageLoadStart = (itemId) => {
  imageLoading.value[itemId] = true
}

// 🔑 图片加载完成
const handleImageLoad = (itemId) => {
  imageLoaded.value[itemId] = true
  imageLoading.value[itemId] = false
  // 预加载下一张图片（如果存在）
  preloadNextImage(itemId)
}

// 🔑 预加载下一张图片
const preloadNextImage = (currentItemId) => {
  const currentIndex = history.value.findIndex(h => h.id === currentItemId)
  if (currentIndex >= 0 && currentIndex < history.value.length - 1) {
    const nextItem = history.value[currentIndex + 1]
    if (nextItem && nextItem.conversionStatus === 2 && !imageLoaded.value[nextItem.id]) {
      const imageUrl = nextItem.thumbnailUrl || nextItem.outputUrl
      if (imageUrl) {
        const link = document.createElement('link')
        link.rel = 'preload'
        link.as = 'image'
        link.href = isProxyUrl(imageUrl) ? sanitizeUrl(imageUrl) : imageUrl.split('?')[0]
        document.head.appendChild(link)
        // 清理预加载链接
        setTimeout(() => link.remove(), 1000)
      }
    }
  }
}

// 处理图片加载错误
const handleImageError = (event) => {
  const img = event.target
  const itemId = img.dataset.itemId
  if (itemId) {
    imageLoaded.value[itemId] = false
    imageLoading.value[itemId] = false
  }
  img.style.display = 'none'
}

// GIF加载完成处理 - 优化性能
const handleGifLoad = (event) => {
  const img = event.target
  // 使用will-change提示浏览器优化
  if (img.classList.contains('preview-gif')) {
    img.style.willChange = 'auto'
  }
}

// 预览错误处理
const handlePreviewError = (event) => {
  console.error('预览加载失败:', event.target.src)
  toastError('预览加载失败，请稍后重试')
}

// 处理ESC键关闭预览
const handleKeydown = (event) => {
  if (event.key === 'Escape' && previewItem.value) {
    closePreview()
  }
}

// 组件挂载时加载历史记录
onMounted(() => {
  loadHistory()
  // 添加键盘事件监听
  document.addEventListener('keydown', handleKeydown)
})

// 组件卸载时清理
onUnmounted(() => {
  // 移除键盘事件监听
  document.removeEventListener('keydown', handleKeydown)
  // 恢复body滚动
  document.body.style.overflow = ''
  if (previewObjectUrl.value) {
    try { URL.revokeObjectURL(previewObjectUrl.value) } catch {}
    previewObjectUrl.value = null
  }
})

// 暴露刷新方法供父组件调用
defineExpose({
  refresh: loadHistory
})
</script>

<style scoped>
.conversion-history {
  margin-top: 30px;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.header-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.header h2 {
  font-size: 24px;
  font-weight: 600;
  color: #1f2937;
  margin: 0;
}

.header h3 {
  font-size: 13px;
  font-weight: 400;
  color: #9ca3af;
  margin: 0;
}

.refresh-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  cursor: pointer;
  font-size: 14px;
  color: #374151;
  transition: all 0.2s;
}

.refresh-btn:hover {
  background: #e5e7eb;
  border-color: #d1d5db;
}

.refresh-btn .icon {
  display: inline-block;
  transition: transform 0.3s;
}

.refresh-btn:hover .icon {
  transform: rotate(180deg);
}

.loading {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 60px 20px;
  color: #6b7280;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f4f6;
  border-top-color: #667eea;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 12px;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.empty {
  text-align: center;
  padding: 60px 20px;
  color: #9ca3af;
}

.empty-icon {
  font-size: 64px;
  margin-bottom: 16px;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.history-item {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 16px;
  background: white;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  transition: all 0.2s;
}

.history-item:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  border-color: #d1d5db;
}

.history-item.status-failed {
  background: #fef2f2;
  border-color: #fecaca;
}

.preview-section {
  flex-shrink: 0;
  width: 120px;
  height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f9fafb;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  /* 🔑 优化：使用GPU加速 */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}

/* 🔑 图片占位符/骨架屏 */
.image-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f3f4f6;
  z-index: 1;
  pointer-events: none;
}

.image-placeholder.hidden {
  display: none;
}

.docx-preview-card {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  background: linear-gradient(135deg, #eef2ff 0%, #e0ecff 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
  text-align: center;
}

.docx-preview-image {
  width: 48px;
  height: 36px;
  object-fit: contain;
  filter: drop-shadow(0 6px 12px rgba(102, 126, 234, 0.3));
}

.docx-preview-filename {
  width: 100%;
  font-size: 0.78rem;
  font-weight: 600;
  color: #4c1d95;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-skeleton {
  width: 60%;
  height: 60%;
  background: linear-gradient(
    90deg,
    #e5e7eb 0%,
    #f3f4f6 50%,
    #e5e7eb 100%
  );
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  border-radius: 4px;
}

@keyframes skeleton-loading {
  0% {
    background-position: 200% 0;
  }
  100% {
    background-position: -200% 0;
  }
}

/* 🔑 图片加载状态 */
.image-loading {
  opacity: 0;
  transition: opacity 0.3s ease-in;
}

.image-loaded {
  opacity: 1;
  transition: opacity 0.3s ease-in;
}

.output-preview,
.thumbnail-preview {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* 🔑 GIF性能优化 */
  image-rendering: -webkit-optimize-contrast;
  backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  /* 🔑 优化：图片加载时的位置 */
  position: relative;
  z-index: 2;
}

.thumbnail-preview {
  /* 缩略图样式，可以添加特殊效果 */
  border-radius: 4px;
}

/* 🔑 GIF缩略图特殊优化 */
.thumbnail-gif {
  will-change: contents;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  contain: layout style paint;
}

/* 🔑 GIF输出预览特殊优化 */
.output-preview-gif {
  will-change: contents;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  contain: layout style paint;
}

/* 为抠图添加棋盘格背景 */
.output-preview.checkered-bg {
  background-image: 
    linear-gradient(45deg, #e5e7eb 25%, transparent 25%),
    linear-gradient(-45deg, #e5e7eb 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, #e5e7eb 75%),
    linear-gradient(-45deg, transparent 75%, #e5e7eb 75%);
  background-size: 16px 16px;
  background-position: 0 0, 0 8px, 8px -8px, -8px 0px;
  padding: 4px;
}

.type-badge {
  position: absolute;
  bottom: 4px;
  right: 4px;
  padding: 2px 6px;
  background: rgba(102, 126, 234, 0.9);
  color: white;
  font-size: 10px;
  font-weight: 600;
  border-radius: 4px;
  backdrop-filter: blur(4px);
  /* 🔑 确保蓝色标题框在图片上面 */
  z-index: 10;
  pointer-events: none;
}

.status-badge {
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
}

.status-badge.converting {
  background: #dbeafe;
  color: #1e40af;
}

.status-badge.failed {
  background: #fee2e2;
  color: #991b1b;
}

.status-badge.pending {
  background: #fef3c7;
  color: #92400e;
}

.info-section {
  flex: 1;
  min-width: 0;
}

.filename {
  font-size: 16px;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta-info {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 13px;
  color: #6b7280;
}

.meta-item {
  display: flex;
  gap: 4px;
}

.meta-item .label {
  font-weight: 500;
}

.error-message {
  margin-top: 8px;
  padding: 8px 12px;
  background: #fee2e2;
  border-radius: 6px;
  font-size: 12px;
  color: #991b1b;
}

.actions {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.action-btn {
  min-width: 60px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 0 12px;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  background: white;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
  color: #374151;
  transition: all 0.2s;
  text-decoration: none;
}

.action-btn:hover {
  background: #f3f4f6;
  border-color: #d1d5db;
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.action-btn:active {
  transform: translateY(0);
}

.action-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.action-btn.preview {
  color: #3b82f6;
  border-color: #bfdbfe;
  background: #eff6ff;
}

.action-btn.preview:hover:not(:disabled) {
  background: #dbeafe;
  border-color: #93c5fd;
}

.action-btn.download {
  color: #0891b2;
  border-color: #a5f3fc;
  background: #ecfeff;
}

.action-btn.download:hover:not(:disabled) {
  background: #cffafe;
  border-color: #67e8f9;
}

.action-btn.delete {
  color: #dc2626;
  border-color: #fecaca;
  background: #fef2f2;
}

.action-btn.delete:hover:not(:disabled) {
  background: #fee2e2;
  border-color: #fca5a5;
}

/* GIF预览模态框 */
.preview-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
  padding: 20px;
  animation: fadeIn 0.2s ease-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.preview-modal-content {
  background: white;
  border-radius: 16px;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  position: relative;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  animation: slideUp 0.3s ease-out;
  overflow: hidden; /* 确保圆角生效，子元素不会超出圆角边界 */
}

@keyframes slideUp {
  from {
    transform: translateY(30px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.preview-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid #e5e7eb;
  background: #f9fafb;
}

.preview-modal-icon {
  width: 42px;
  height: 32px;
  object-fit: contain;
}

.preview-modal-title {
  flex: 1;
  font-size: 18px;
  font-weight: 600;
  color: #1f2937;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preview-close-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, 0.6);
  color: white;
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.preview-close-btn:hover {
  background: rgba(0, 0, 0, 0.8);
  transform: rotate(90deg);
}

.preview-modal-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px 20px;
  font-size: 13px;
  color: #6b7280;
  border-bottom: 1px solid #f3f4f6;
}

.preview-file-container {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 20px 20px 20px;
  overflow: auto;
  min-height: 300px;
  position: relative;
  /* 🔑 确保顶部圆角效果 */
  border-radius: 16px 16px 0 0;
  /* 🔑 GIF容器性能优化 */
  will-change: scroll-position;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  /* 使用GPU加速滚动 */
  -webkit-overflow-scrolling: touch;
}

/* 预览加载等待页面 */
.preview-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.95);
  z-index: 5;
  gap: 16px;
  /* 🔑 确保加载页面也遵循顶部圆角 */
  border-radius: 16px 16px 0 0;
}

.preview-loading-spinner {
  width: 50px;
  height: 50px;
  border: 4px solid #f3f4f6;
  border-top-color: #667eea;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.preview-loading-text {
  font-size: 16px;
  font-weight: 600;
  color: #374151;
  margin: 0;
}

.preview-loading-hint {
  font-size: 13px;
  color: #6b7280;
  margin: 0;
}

.preview-file {
  max-width: 100%;
  max-height: 60vh;
  object-fit: contain;
  border-radius: 8px;
  /* 🔑 GIF性能优化 */
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
  backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}

/* 🔑 GIF预览优化 - 硬件加速和性能优化 */
.preview-gif {
  will-change: contents;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
  /* 使用GPU加速 */
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  /* 优化渲染 */
  image-rendering: auto;
  -webkit-font-smoothing: antialiased;
  /* 减少重绘 */
  contain: layout style paint;
}

.preview-svg {
  width: 100%;
  height: 60vh;
}
.preview-svg-img {
  width: 100%;
  height: 60vh;
  object-fit: contain;
}

.preview-pdf-frame {
  width: 100%;
  height: 520px;
  border: none;
  border-radius: 12px;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.06);
}
.preview-placeholder-text {
  font-size: 14px;
  color: #6b7280;
}

.preview-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 16px 20px;
  border-top: 1px solid #e5e7eb;
  background: #f9fafb;
}

.preview-modal-btn {
  min-width: 120px;
  padding: 10px 18px;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.preview-modal-btn.primary {
  background: #ecfeff;
  border-color: #a5f3fc;
  color: #0e7490;
}

.preview-modal-btn.primary:hover:not(:disabled) {
  background: #cffafe;
  border-color: #67e8f9;
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(14, 116, 144, 0.2);
}

.preview-modal-btn.secondary {
  background: white;
  color: #9ca3af;
}

.preview-modal-btn.secondary:hover {
  background: #f3f4f6;
}

.preview-modal-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .history-item {
    flex-direction: column;
    align-items: stretch;
  }
  
  .preview-section {
    width: 100%;
    height: 160px;
  }
  
  .info-section {
    text-align: center;
  }
  
  .meta-info {
    justify-content: center;
  }
  
  .actions {
    justify-content: center;
  }
  
  .preview-modal-content {
    max-width: 95vw;
    max-height: 95vh;
  }
  
  .preview-file {
    max-height: 50vh;
  }
  
  .preview-svg {
    height: 50vh;
  }
  
  .preview-filename {
    font-size: 14px;
  }
  
  .preview-meta {
    font-size: 12px;
    gap: 10px;
  }
}
</style>

